home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Camelot / Camelot 043 (1989-06)(Swedish User Group of Amiga)(SE)(PD)[WB].zip / Camelot 043 (1989-06)(Swedish User Group of Amiga)(SE)(PD)[WB].adf / zc / gsub.c < prev    next >
C/C++ Source or Header  |  1989-03-08  |  8KB  |  482 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  *
  11.  *    gsub.c
  12.  *
  13.  *    Various code generation subroutines
  14.  *    Includes generation of switches and
  15.  *    conversion of type lists to simple type,size.
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include "param.h"
  20. #include "bstok.h"
  21. #include "tytok.h"
  22. #include "flags.h"
  23. #include "nodes.h"
  24. #include "gen.h"
  25.  
  26. #define isimmed(np)     ((np)->g_flags & IMMEDID)
  27. #define isareg(np)      ((np)->g_token == REGVAR && (np)->g_rno >= AREG)
  28.  
  29. extern cctest;
  30.  
  31. extern xflags[];
  32. #define debug    xflags['s'-'a']
  33.  
  34. gen_brt(np, lbl)
  35. NODEP np;
  36. {
  37.     p2_expr(&np);
  38.     mustty(np, R_SCALAR);
  39.     br_sub(np, 0, lbl);
  40. }
  41.  
  42. gen_brf(np, lbl)
  43. NODEP np;
  44. {
  45.     p2_expr(&np);
  46.     mustty(np, R_SCALAR);
  47.     br_sub(np, 1, lbl);
  48. }
  49.  
  50. br_sub(np, rev, lbl)
  51. NODEP np;
  52. {
  53.     int i;
  54.  
  55.     switch (np->e_token) {
  56.         case DOUBLE '&':
  57.             br_split(np, lbl, rev);
  58.             return;
  59.         case DOUBLE '|':
  60.             br_split(np, lbl, 2+rev);
  61.             return;
  62.     }
  63.     genx(np, FORCC);
  64.     i = cctest;
  65.     if (i) {
  66.         if (rev)
  67.             /* reverse truth */
  68.             i = (i&1) ? i+1 : i-1;
  69.         out_b(i, lbl);
  70.     }
  71. }
  72.  
  73. br_split(np, lbl, n)
  74. NODEP np;
  75. {
  76.     int nlbl;
  77.  
  78.     if (n == 0 || n == 3)
  79.         nlbl = new_lbl();
  80.     else
  81.         nlbl = lbl;
  82.  
  83.     br_sub(np->n_left, n<2, nlbl);
  84.     br_sub(np->n_right, n&1, lbl);
  85.  
  86.     freeunit(np);
  87.  
  88.     if (nlbl != lbl)
  89.         def_lbl(nlbl);
  90. }
  91.  
  92. /* generate switch
  93.     np - list of nodes with value,label pairs (sorted)
  94.     dlbl - default label or -1
  95.  */
  96. #undef min
  97. #undef max
  98.  
  99. gen_switch(np, odlbl)
  100. NODEP np;
  101. {
  102.     int n,min,max;
  103.     int dlbl;
  104.     register NODEP p;
  105.  
  106.     if (debug) {
  107.         printf("gs %d ", odlbl);
  108.         printnode(np);
  109.     }
  110.  
  111.     /* if no default, make one! */
  112.     if (odlbl < 0)
  113.         dlbl = new_lbl();
  114.     else
  115.         dlbl = odlbl;
  116.  
  117.     n = 0;
  118.     for (p=np; p; p=p->n_next) {
  119.         if (n == 0)
  120.             min = max = p->c_casev;
  121.         else
  122.             max = p->c_casev;
  123.         n++;
  124.     }
  125.     if (n <= C_SIMPLE)
  126.         simple_sw(np,odlbl);
  127.     else if (n >= max/C_RATIO - min/C_RATIO)
  128.         table_sw(np,dlbl,min,max);
  129.     else {
  130.         half_sw(np,dlbl,max/2+min/2,n);
  131.         goto out;        /* free already done */
  132.     }
  133.     freenode(np);
  134. out:
  135.     if (odlbl < 0)
  136.         def_lbl(dlbl);
  137. }
  138.  
  139. /* simple if-else type switch
  140.     dlbl may be -1 -> fall through
  141.     does not free np
  142. */
  143. simple_sw(np, dlbl)
  144. register NODEP np;
  145. {
  146.     while (np) {
  147.         out_d0cmp(np->c_casev);
  148.         out_b(B_EQ, np->c_casel);
  149.         np = np->n_next;
  150.     }
  151.     if (dlbl >= 0)
  152.         out_br(dlbl);
  153. }
  154.  
  155. /* use table switch
  156.     dlbl is not -1
  157.     does not free np
  158. */
  159. table_sw(np, dlbl, min, max)
  160. NODEP np;
  161. {
  162.     out_d0cmp(min);
  163.     out_b(B_LT, dlbl);
  164.     out_d0cmp(max);
  165.     out_b(B_GT, dlbl);
  166.     if (min)
  167.         out_d0sub(min);
  168.  
  169.     out_tsw();
  170.  
  171.     while (np) {
  172.         while (min < np->c_casev) {
  173.             out_tlbl(dlbl);
  174.             min++;
  175.         }
  176.         out_tlbl(np->c_casel);
  177.         min++;
  178.         np = np->n_next;
  179.     }
  180. }
  181.  
  182. /* cut switch in half (by value)
  183.     dlbl is not -1
  184.     will free np
  185.  */
  186. half_sw(np, dlbl, cut, n)
  187. NODEP np;
  188. {
  189.     register NODEP p, last;
  190.     int nlo, nhi;
  191.     int l1;
  192.  
  193.     for (p=np; p->c_casev < cut; p = p->n_next)
  194.         last = p;
  195.     /* we KNOW both pieces are non-NULL ! */
  196.     last->n_next = NULL;
  197.     last = p;
  198.  
  199.     nlo = 0;
  200.     nhi = 0;
  201.     for (p=np; p; p=p->n_next)
  202.         nlo++;
  203.     nhi = n - nlo;
  204.  
  205.     if (nhi == 1) {         /* switch hi and low */
  206.         p = np;
  207.         np = last;
  208.         last = p;
  209.         nlo = 1;
  210.         nhi = n-1;
  211.     }
  212.     if (nlo == 1) {         /* also nhi == 1 */
  213.         out_d0cmp(np->c_casev);
  214.         out_b(B_EQ, np->c_casel);
  215.         freenode(np);
  216.         gen_switch(last, dlbl);
  217.         return;
  218.     }
  219.     l1 = new_lbl();
  220.     out_d0cmp(cut);
  221.     out_b(B_GE, l1);
  222.     gen_switch(np, dlbl);
  223.     def_lbl(l1);
  224.     gen_switch(last, dlbl);
  225. }
  226.  
  227. istempa(np)
  228. register NODEP np;
  229. {
  230.     if (np->g_token == OREG && istemp(np->g_rno))
  231.         return 1;
  232.     return 0;
  233. }
  234.  
  235. strasn(np)
  236. NODEP np;
  237. {
  238.     int r;
  239.     long size;
  240.     int chunk, l;
  241.     char buf[40];
  242.     int lisa, risa;
  243.  
  244.     if (np->g_ty != ET_A)
  245.         return 0;
  246.  
  247.     size = np->g_bsize;
  248.     if (size <= 4) {        /* pretend its scalar */
  249.         np->g_sz = size;
  250.         return 0;
  251.     }
  252.  
  253.     lisa = istempa(np->n_left);
  254.     risa = istempa(np->n_right);
  255.  
  256.     if (lisa)
  257.         r = np->n_left->g_rno;
  258.     else
  259.         r = ralloc(AREG);       /* R0 */
  260.     indir(np, r);
  261.     np->g_offs = -size;
  262.  
  263.     if (size & 3)
  264.         chunk = 2;
  265.     else
  266.         chunk = 4;
  267.  
  268.     if (risa)
  269.         np->g_r1 = np->n_right->g_rno;
  270.     else
  271.         tempr(np, AREG);        /* R1 */
  272.     tempr(np, 0);           /* R2 */
  273.  
  274.     if (!lisa || np->n_left->g_offs)
  275.         addcode(np, "\tlea\t<A,R0\n");
  276.     if (!risa || np->n_right->g_offs)
  277.         addcode(np, "\tlea\t>A,R1\n");
  278.     np->g_bsize = size/chunk - 1;
  279.     addcode(np, "\tmove.w\t#K,R2\n");
  280.     l = new_lbl();
  281.     sprintf(buf, "'L%d:\tmove.%c\t(R1)+,(R0)+\n", l, chunk == 4 ?
  282.         'l' : 'w');
  283.     addcode(np, buf);
  284.     sprintf(buf, "\tdbra\tR2,'L%d\n", l);
  285.     addcode(np, buf);
  286.  
  287.     return 1;
  288. }
  289.  
  290.  
  291. extern funstrl;
  292. strret(np)
  293. NODEP np;
  294. {
  295.  
  296.     strsub(np, funstrl);
  297. }
  298.  
  299. strpush(np)
  300. NODEP np;
  301. {
  302.     strsub(np, 0);
  303. }
  304.  
  305. strsub(np, tolbl)
  306. register NODEP np;
  307. {
  308.     long size;
  309.     int chunk, l;
  310.     char buf[40];
  311.     char *frstr;
  312.  
  313.     size = np->g_bsize;
  314.     if (size & 3)
  315.         chunk = 2;
  316.     else
  317.         chunk = 4;
  318.  
  319.     tempr(np, 0);
  320.  
  321.     /* set up 'from' address */
  322.     if (np->g_token == OREG && istemp(np->g_rno)) {
  323.         frstr = "R0";
  324.         if (np->g_offs)
  325.             addcode(np, "\tlea\tA,R0\n");
  326.     } else {
  327.         frstr = "a1";
  328.         addcode(np, "\tlea\tA,a1\n");
  329.     }
  330.  
  331.     /* set up 'to' address */
  332.     if (tolbl) {
  333.         sprintf(buf, "\tmove.l\t#'L%d,a2\n", tolbl);
  334.         addcode(np, buf);
  335.     } else {
  336.         sprintf(buf, "\tsub\t#%d,sp\n", (int)size);
  337.         addcode(np, buf);
  338.         addcode(np, "\tmove.l\tsp,a2\n");
  339.     }
  340.  
  341.     /* generate copy loop */
  342.     np->g_bsize = size/chunk - 1;
  343.     addcode(np, "\tmove.w\t#K,R1\n");
  344.     l = new_lbl();
  345.     sprintf(buf, "'L%d:\tmove.%c\t(%s)+,(a2)+\n", l, chunk == 4 ?
  346.         'l' : 'w', frstr);
  347.     addcode(np, buf);
  348.     sprintf(buf, "\tdbra\tR1,'L%d\n", l);
  349.     addcode(np, buf);
  350. }
  351.  
  352. specasn(np, flags)
  353. NODEP np;
  354. {
  355.     NODEP lp = np->n_left, rp = np->n_right;
  356.     int r;
  357.  
  358.     if (rp->g_token == ICON && isimmed(rp)) {
  359.         rinherit(np);
  360.  
  361.         if (rp->g_offs == 0 && !isareg(rp))
  362.             addcode(np, "\tclr.S\t<A\n");
  363.         else
  364.             addcode(np, "\tmove.S\t>A,<A\n");
  365.         return 1;
  366.     }
  367.     if (rp->g_token == OREG && isimmed(rp)) {
  368.         rp->g_flags &= ~IMMEDID;
  369.         if (isareg(lp)) {
  370.             inherit(np);
  371.             addcode(np, "\tlea\t>A,A\n");
  372.         } else {
  373.             r = ralloc(AREG);
  374.             retreg(np, r);
  375.             addcode(np, "\tlea\t>A,A\n");
  376.             addcode(np, "\tmove.l\tA,<A\n");
  377.         }
  378.         return 1;
  379.     }
  380.     return 0;
  381. }
  382.  
  383. untype(np)
  384. register NODEP np;
  385. {
  386.     if (np == NULL || np->n_tptr == NULL) {
  387.         printf("? NULL untype ");
  388.         return;
  389.     }
  390.  
  391.     switch (np->e_type) {
  392.     case E_BIN:
  393.         untype(np->n_right);
  394.         /* fall through */
  395.     case E_UNARY:
  396.         if (np->e_token == '.' && np->e_fldw) {
  397.             np->g_fldw = np->e_fldw;
  398.             np->g_fldo = np->e_fldo;
  399.         } else
  400.             np->g_fldw = 0;
  401.  
  402.         untype(np->n_left);
  403.     }
  404.  
  405.     get_tyinf(np);
  406.  
  407.     if ((np->n_flags & N_COPYT) == 0)
  408.         freenode(np->n_tptr);
  409.     np->n_tptr = NULL;        /* is g_code */
  410.     np->g_betw = NULL;
  411. }
  412.  
  413. static char bty[] = {
  414.     ET_U, ET_U, ET_S, ET_S, ET_U, ET_S, ET_S, ET_F, ET_F, 0
  415. };
  416.  
  417. static char bsz[] = {
  418.     SIZE_C, SIZE_L, SIZE_L, SIZE_S, SIZE_U,
  419.     SIZE_I, SIZE_C, SIZE_F, SIZE_D, 0
  420. };
  421.  
  422. get_tyinf(np)
  423. register NODEP np;
  424. {
  425.     NODEP tp = np->n_tptr;
  426.     int n;
  427.     long offs;
  428.  
  429.     offs = np->e_offs;
  430.  
  431.     /* inherit name,token,left,right,nmx from common
  432.         and token, flags, type, sc from enode */
  433.  
  434.     switch (tp->t_token) {
  435.     case K_STRUCT:
  436.     case K_UNION:
  437.         np->g_bsize = tp->t_size;
  438.         np->g_ty = ET_A;
  439.         np->g_sz = 0;
  440.         break;
  441.     case '(':
  442.         break;
  443.     case STAR:
  444.         np->g_ty = ET_U;
  445.         np->g_sz = SIZE_P;
  446.         break;
  447.     default:
  448.         n = tp->t_token-FIRST_BAS;
  449.         np->g_ty = bty[n];
  450.         np->g_sz = bsz[n];
  451.     }
  452.     np->g_offs = offs;    /* different place */
  453. }
  454.  
  455. addcode(np, s)
  456. register NODEP np;
  457. char *s;
  458. {
  459.     NODEP tp;
  460.     int i, c;
  461.  
  462.     while (np->g_code)
  463.         np = np->g_code;
  464.     tp = allocnode();
  465.     np->g_code = tp;
  466.     np->n_flags &= ~N_COPYT;
  467.     i = strlen(s);
  468.     if (i < NMXSIZE) {      /* fits in one */
  469.         strcpy(tp->n_name, s);
  470.         return;
  471.     }
  472.  
  473.     /* need to split it */
  474.     i = NMXSIZE-1;
  475.     c = s[i-1];
  476.     if (c == '<' || c == '>' || (c>='A' && c<='Z')) /* special */
  477.         i--;
  478.     strncpy(tp->n_name, s, i);
  479.     tp->n_name[i] = 0;
  480.     addcode(tp, &s[i]);
  481. }
  482.